package com.turing.post.account.impl;

import java.math.BigInteger;
import java.util.Date;

import javax.ejb.EJB;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;

import com.turing.post.account.util.BankAssoc;
import com.turing.post.account.util.BankAssocDao;
import com.turing.post.account.util.OnlineTransferDetail;
import com.turing.post.account.util.OnlineTransferDetailBusiness;
import com.turing.post.account.util.OnlineTransferDetailDao;
import com.turing.post.cardmanagement.util.ActivateCard;
import com.turing.post.cardmanagement.util.ActivateCardDao;
import com.turing.post.cardmanagement.util.CardClassic;
import com.turing.post.cardmanagement.util.CardClassicDao;
import com.turing.post.cardmanagement.util.MakeCardControl;
import com.turing.post.cardmanagement.util.MakeCardControlDao;
import com.turing.post.common.util.PCPSCommonDao;
import com.turing.post.organization.util.BankManage;
import com.turing.post.organization.util.BankManageDao;
import com.turing.post.organization.util.BankTranBusinessAgent;
import com.turing.post.organization.util.IssueCompany;
import com.turing.post.organization.util.IssueCompanyDao;
import com.turing.post.util.PCPSApplicationException;
import com.turing.post.util.PCPSUtil;
import com.turing.post.util.PCPSWebInput;

/**
 * 联机转账明细
 * 
 * @author kangzhe
 * 
 */
@Stateless(mappedName = "account.impl.OnlineTransferDetailBusinessImpl")
@Remote
@Local
public class OnlineTransferDetailBusinessImpl implements
		OnlineTransferDetailBusiness {

	@EJB(mappedName = "account.impl.OnlineTransferDetailDaoImpl")
	private OnlineTransferDetailDao otdDao;

	@EJB(mappedName = "cardmanagement.impl.ActivateCardDaoImpl")
	private ActivateCardDao acDao;

	@EJB(mappedName = "organization.impl.IssueCompanyDaoImpl")
	private IssueCompanyDao issueCompanyDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.MakeCardControlDaoImpl")
	private MakeCardControlDao makeCardControlDaoImpl;

	@EJB(mappedName = "cardmanagement.impl.CardClassicDaoImpl")
	private CardClassicDao cardClassicDaoImpl;

	@EJB(mappedName = "common.impl.PCPSCommonDaoImpl")
	private PCPSCommonDao pcpsCommonDaoImpl;

	@EJB(mappedName = "account.impl.BankAssocDaoImpl")
	private BankAssocDao bankAssocDao;

	@EJB(mappedName = "organization.impl.BankManageDaoImpl")
	private BankManageDao bmDao;

	@EJB(mappedName = "account.impl.OnlineTransferDetailBusinessImpl")
	private OnlineTransferDetailBusiness OnlineTransferDetailBusinessImpl;
	
	/**
	 * 异常抛出方法
	 * 
	 * @param error
	 * @throws PCPSApplicationException
	 */
	private void errException(String error) throws PCPSApplicationException {
		throw new PCPSApplicationException(
				PCPSApplicationException.ERRCODE_CATEGORY_APPLICATION, "",
				error);
	}

	/**
	 * 检查卡余额是否超过限制
	 * 
	 * @param cardNo
	 * @param newbal
	 * @param issueCompany
	 * @param cardClassic
	 * @throws PCPSApplicationException
	 */
	private void checkBalanceLimit(String cardNo, BigInteger newbal,
			IssueCompany issueCompany, CardClassic cardClassic)
			throws PCPSApplicationException {
		BigInteger ballim = cardClassic.getBalanceLimit();
		int result = BigInteger.ZERO.compareTo(ballim);
		if (result > 0)
			errException("卡种类[" + cardClassic.getCardClassicName()
					+ "]余额限制参数非法!");
		if (result == 0)
			ballim = issueCompany.getEachCardBalanceLimit();

		result = BigInteger.ZERO.compareTo(ballim);
		if (result > 0)
			errException("发卡商[" + issueCompany.getIssueCompanyNo()
					+ "]余额限制参数非法!");
		if (result == 0)
			return;

		if (newbal.compareTo(ballim) > 0)
			errException("卡号[" + cardNo + "]余额/交易后余额超过系统限制!");
	}

	@Override
	public void onlineTransferDeposit(PCPSWebInput webInput, String cardNo,
			BigInteger amount, BigInteger bankManageId, String remark)
			throws PCPSApplicationException {
		// 1. 参数合法性检查
		// 入口参数检查
		if (webInput == null || webInput.getOperId() == null) {
			errException("登录信息为空!");
		}
		if (PCPSUtil.isEmpty(cardNo)) {
			errException("卡号为空!");
		}
		if (amount == null || amount.compareTo(BigInteger.ZERO) < 1) {
			errException("转账金额不合法!");
		}
		if (bankManageId == null) {
			errException("银行信息为空!");
		}
		ActivateCard ac = acDao.getActivateCardByCardNo(cardNo);
		if (ac == null) {
			errException("卡信息未找到!");
		}
		// 判断销卡状态 -- 不等于未销卡
		if (!PCPSUtil.compareObject(ac.getCloseStatus(),
				ActivateCard.ACTIVATECARD_CLOSESTATUS_NORMAL))
			errException("卡" + cardNo + "已经注销!");

		// 判断挂失状态 -- 等于正式挂失或者临时挂失
		if (PCPSUtil.compareObject(ac.getLossStatus(),
				ActivateCard.ACTIVATECARD_LOSSSTATUS_LOSSED)
				|| PCPSUtil.compareObject(ac.getLossStatus(),
						ActivateCard.ACTIVATECARD_LOSSSTATUS_TEMP_LOSSED))
			errException("卡" + cardNo + "已经挂失!");

		// 检索制卡控制批次
		MakeCardControl mcc = makeCardControlDaoImpl
				.getMakeCardControlByBatchNo(ac.getBatchNo());

		// 取卡种类
		CardClassic cardClassic = cardClassicDaoImpl
				.getCardClassicByCardClassicId(ac.getCardClassicId());

		// 取卡系统全局数据字典
		IssueCompany issueCompany = issueCompanyDaoImpl
				.getIssueCompanyByIssueCompanyNo(PCPSUtil.getIssueCompanyNo(webInput));

		// 卡的归属必须是同一发卡商
		if (!PCPSUtil.compareObject(mcc.getIssueCompanyNo(), issueCompany
				.getIssueCompanyNo()))
			errException("非本发卡商发行的卡!");

		// 取当前时间
		Date tranTime = pcpsCommonDaoImpl.getDatabaseSysTime();

		// 本次充值后金额超限检查
		BigInteger newbal = ac.getBalance().add(amount);
		checkBalanceLimit(cardNo, newbal, issueCompany, cardClassic);

		// 2. 记本地流水,单独事务已提交
		String localSeqNo = OnlineTransferDetailBusinessImpl.insertOnlineTransferDetail(webInput, issueCompany,
				cardNo, amount, bankManageId, ac.getMasterAccNo(), tranTime,
				remark);

		// 3. 调银行端处理
		BankManage bm = bmDao.getBankManageByBankManageId(bankManageId);
		if (bm == null) {
			errException("未找到银行对应管理信息!");
		}
		BankTranBusinessAgent.BankCardOnlineTransfer(bm, localSeqNo);
	}

	/**
	 * 记本地流水信息(联机转账明细)
	 * 独立事务
	 * @param webInput
	 * @param issueCompany
	 * @param cardNo
	 * @param amount
	 * @param bankManageId
	 * @param masterAccNo
	 * @param remark
	 * @throws PCPSApplicationException
	 */
	@TransactionAttribute(javax.ejb.TransactionAttributeType.REQUIRES_NEW)
	public String insertOnlineTransferDetail(PCPSWebInput webInput,
			IssueCompany issueCompany, String cardNo, BigInteger amount,
			BigInteger bankManageId, BigInteger masterAccNo, Date tranTime,
			String remark) throws PCPSApplicationException {
		OnlineTransferDetail otd = new OnlineTransferDetail();
		// 业务单号
		String localSeqNo = pcpsCommonDaoImpl.getOrderNumber(tranTime, webInput
				.getOperBranchNo());
		otd.setLocalSeqNo(localSeqNo);
		otd.setIssueCompanyNo(issueCompany.getIssueCompanyNo());
		otd.setSaleBranchNo(webInput.getOperBranchNo());
		otd.setTrandate(issueCompany.getTranDate());
		otd.setTranTime(tranTime);
		otd.setMasterAccNo(masterAccNo);
		otd.setBankManageId(bankManageId);
		BankAssoc ba = bankAssocDao.getBankAssoc(bankManageId, masterAccNo);
		if(ba == null){
			errException("未找到卡片与银行签约的信息!");
		}
		otd.setAccNo(ba.getAccNo());
		otd.setTranType(OnlineTransferDetail.OnlineTransfer_TranType_deposit);
		otd.setStatus(OnlineTransferDetail.OnlineTransfer_Status_create);
		otd.setCheckStatus(OnlineTransferDetail.OnlineTransfer_CheckStatus_create);
		otd.setCardNo(cardNo);
		otd.setAmount(amount);
		otd.setOperId(webInput.getOperId());
		otd.setRemark(remark);
		otdDao.insert(otd);
		return localSeqNo;
	}

}
